package com.beemans.common.ext

import android.graphics.Typeface
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.view.contains
import androidx.core.view.isNotEmpty
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LifecycleOwner
import androidx.navigation.Navigation
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.beemans.common.ui.views.CustomDivider
import com.beemans.common.ui.views.TitleBarLayout
import com.tiamosu.fly.base.BaseFlyActivity
import com.tiamosu.fly.base.BaseFlyFragment
import com.tiamosu.fly.ext.clickNoRepeat

/**
 * @author tiamosu
 * @date 2021/3/12
 */

/**
 * 获取上下文
 */
val LifecycleOwner.context: FragmentActivity
    get() {
        return when (this) {
            is BaseFlyFragment -> context
            is Fragment -> requireActivity()
            is BaseFlyActivity -> this
            is FragmentActivity -> this
            else -> throw IllegalArgumentException("owner must is Fragment or FragmentActivity")
        }
    }

/**
 * 绑定 Recyclerview
 *
 * @param layoutManger 布局管理器
 * @param bindAdapter 适配器
 * @param itemDecoration 分割线
 * @param isScroll 当滑动控件嵌套 RecyclerView 时，设置为 false，把 RecyclerView 的滑动焦点交给父控件
 * @param hasFixedSize 当我们确定 item 的改变不会影响 RecyclerView 的宽高的时候可以设置 setHasFixedSize(true)，
 * 并通过 Adapter 的增删改插方法去刷新 RecyclerView，而不是通过 notifyDataSetChanged()。
 * （其实可以直接设置为 true，当需要改变宽高的时候就用 notifyDataSetChanged() 去整体刷新一下）
 */
fun RecyclerView.init(
    layoutManger: RecyclerView.LayoutManager = LinearLayoutManager(context),
    bindAdapter: RecyclerView.Adapter<*>,
    itemDecoration: RecyclerView.ItemDecoration = CustomDivider(),
    isScroll: Boolean = true,
    hasFixedSize: Boolean = true
): RecyclerView {
    layoutManager = layoutManger
    addItemDecoration(itemDecoration)
    setHasFixedSize(hasFixedSize)
    adapter = bindAdapter
    if (!isScroll) {
        //解决卡顿、滚动粘连
        this.isNestedScrollingEnabled = false
        //如果不设置 false 会引起滚动条初始化的时候滚到 RecyclerView 的位置
        this.isFocusable = false
    }
    return this
}

/**
 * ViewPager2 初始化
 */
fun ViewPager2.init(
    fragment: Fragment,
    fragments: List<Class<out Fragment>>,
    offscreenPageLimit: Int = fragments.size,
    maxOffscreenPageLimit: Int = fragments.size,
    isUserInputEnabled: Boolean = false,
    createFragment: (fragment: Fragment, position: Int) -> Unit = { _: Fragment, _: Int -> }
): ViewPager2 {
    //是否可滑动
    this.isUserInputEnabled = isUserInputEnabled

    //设置页面预加载数量
    if (offscreenPageLimit > 0) {
        this.offscreenPageLimit = offscreenPageLimit.coerceAtMost(maxOffscreenPageLimit)
    }

    //设置适配器
    adapter = object : FragmentStateAdapter(fragment) {
        override fun createFragment(position: Int): Fragment {
            return fragments[position].newInstance().apply {
                createFragment.invoke(this, position)
            }
        }

        override fun getItemCount() = fragments.size
    }
    return this
}

/**
 * @param isNavigateUp 是否执行Fragment的返回上一页
 * @param onClick 点击回调，自定义进行点击事件处理
 *
 * @return 设置页面返回事件
 */
fun TitleBarLayout.setPageBack(
    isNavigateUp: Boolean = true,
    onClick: () -> Unit = {}
) {
    setIvLeft {
        clickNoRepeat {
            onClick.invoke()
            if (isNavigateUp) {
                Navigation.findNavController(this).navigateUp()
            }
        }
    }
}

/**
 * 视图变化监听
 */
fun View.addOnGlobalLayoutListener(onGlobalLayoutListener: () -> Unit) {
    val vto = viewTreeObserver
    if (!vto.isAlive) {
        return
    }
    vto.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        @Suppress("DEPRECATION")
        override fun onGlobalLayout() {
            val currentVto = viewTreeObserver
            if (currentVto.isAlive) {
                currentVto.removeOnGlobalLayoutListener(this)
            }
            onGlobalLayoutListener()
        }
    })
}

/**
 * 获取 RecyclerView 滚动的真实距离
 */
fun getRvRealScrollX(layoutManager: LinearLayoutManager): Int {
    //找到即将移出屏幕Item的position,position是移出屏幕item的数量
    val position = layoutManager.findFirstVisibleItemPosition()
    //根据position找到这个Item
    val firstVisibleChildView = layoutManager.findViewByPosition(position) ?: return 0
    //获取Item的宽
    val itemWidth = firstVisibleChildView.width
    //算出该Item还未移出屏幕的高度
    val itemRight = firstVisibleChildView.right
    //position移出屏幕的数量*高度得出移动的距离
    val iPosition = position * itemWidth
    //因为横着的RecyclerV第一个取到的Item position为零所以计算时需要加一个宽
    return iPosition - itemRight + itemWidth
}

/**
 * 设置控件外间距
 */
inline fun View.updateMarginLayoutParams(block: ViewGroup.MarginLayoutParams.() -> Unit) {
    (layoutParams as? ViewGroup.MarginLayoutParams)?.apply {
        block.invoke(this)
        layoutParams = this
    }
}

/**
 * 设定[AppCompatTextView]文字大小
 */
fun <T : TextView> T.updateTextSize(
    textSize: Float,
    unit: Int = TypedValue.COMPLEX_UNIT_PX
): T {
    setTextSize(unit, textSize)
    return this
}

/**
 * 设定[AppCompatTextView]粗体
 */
fun <T : TextView> T.updateTextBold(isBold: Boolean = true): T {
    val style = if (isBold) Typeface.BOLD else Typeface.NORMAL
    typeface = Typeface.defaultFromStyle(style)
    return this
}

/**
 * 添加子视图
 */
fun ViewGroup?.addChildView(
    view: View?,
    params: ViewGroup.LayoutParams? = null
) {
    if (view == null || this == null || contains(view)) return

    removeAllChildView()
    view.removeFromParent()

    when {
        params != null -> addView(view, params)
        else -> addView(view)
    }
}

/**
 * 移除所有子视图
 */
fun ViewGroup?.removeAllChildView() {
    if (this?.isNotEmpty() == true) {
        this.removeAllViews()
    }
}

/**
 * 从父布局移除视图
 */
fun View?.removeFromParent() {
    (this?.parent as? ViewGroup)?.removeView(this)
}